package net.mikoo.seals.api.controller;

import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import javax.servlet.http.HttpServletRequest;

import org.apache.avalon.framework.parameters.ParameterException;
import org.apache.commons.lang.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;

import net.mikoo.seals.api.model.BaseResponse;
import net.mikoo.seals.api.model.ResultType;
import net.mikoo.seals.api.model.devices.AddDevicesRequest;
import net.mikoo.seals.api.model.devices.BindDevicesRequest;
import net.mikoo.seals.api.model.devices.DevicesPositionRequest;
import net.mikoo.seals.api.model.devices.DevicesPositionResponse;
import net.mikoo.seals.api.model.devices.EditSealRequest;
import net.mikoo.seals.api.model.devices.GetDetailRequest;
import net.mikoo.seals.api.model.devices.GetDetailResponse;
import net.mikoo.seals.api.model.devices.GetListRequest;
import net.mikoo.seals.api.model.devices.GetListResponse;
import net.mikoo.seals.api.model.devices.InstallDevicesRequest;
import net.mikoo.seals.api.model.devices.OpenRequest;
import net.mikoo.seals.api.model.devices.ReleaseInterimRequest;
import net.mikoo.seals.api.model.devices.ResetStatusRequest;
import net.mikoo.seals.api.model.devices.SetCustRequest;
import net.mikoo.seals.api.model.devices.SetInterimRequest;
import net.mikoo.seals.api.model.devices.SetWorkflowRequest;
import net.mikoo.seals.api.model.devices.SwitchRunStatusRequest;
import net.mikoo.seals.api.model.devices.SyncDevicesStatusRequest;
import net.mikoo.seals.api.model.devices.UpgradeRequest;
import net.mikoo.seals.api.model.seal.SealListRequest.PurposeEnum;
import net.mikoo.seals.api.utility.PartyUtility;
import net.mikoo.seals.biz.service.DevicesActService;
import net.mikoo.seals.biz.service.DevicesServices;
import net.mikoo.seals.biz.service.DevicesTakeService;
import net.mikoo.seals.biz.service.DevicesUsedServices;
import net.mikoo.seals.biz.service.SealServices;
import net.mikoo.seals.common.enums.ApplyTypeEnum;
import net.mikoo.seals.common.enums.DevicesStatusEnum;
import net.mikoo.seals.common.enums.TakeStatusEnum;
import net.mikoo.seals.common.enums.WorkflowTypeEnum;
import net.mikoo.seals.common.exception.NeedBackMsgException;
import net.mikoo.seals.common.model.PageModel;
import net.mikoo.seals.model.Devices;
import net.mikoo.seals.model.DevicesAct;
import net.mikoo.seals.model.DevicesActQuery;
import net.mikoo.seals.model.DevicesQuery;
import net.mikoo.seals.model.DevicesTake;
import net.mikoo.seals.model.DevicesTakeQuery;
import net.mikoo.seals.model.Seal;
import net.mikoo.seals.model.SealQuery;

@Controller
public class DevicesController {

	private static Logger logger = LoggerFactory.getLogger(DevicesController.class);
	
	@Autowired
	private DevicesServices devicesServices;
	
	@Autowired
	private DevicesActService devicesActService;
	
	@Autowired
	private DevicesUsedServices devicesUsedServices;
	
	@Autowired
	private DevicesTakeService devicesTakeService;
	
	@Autowired
	private SealServices sealServices;
	
	@RequestMapping("/devices/list")
	@ResponseBody
	public GetListResponse list(GetListRequest getListRequest, HttpServletRequest request) {
		GetListResponse response = new GetListResponse();
		try {
			
			if(getListRequest == null) {
				throw new IllegalArgumentException("getListRequest");
			}
			
			if(getListRequest.getPageNo() == null || getListRequest.getPageNo() < 1) {
				getListRequest.setPageNo(1);
			}
			
			if(getListRequest.getPageSize() == null || getListRequest.getPageSize() < 1) {
				getListRequest.setPageSize(10);;
			}
			
			DevicesQuery query = new DevicesQuery();
			
			PurposeEnum purpose = PurposeEnum.getByCode(getListRequest.getPurpose());
			if(purpose == PurposeEnum.ADMIN_SEAL_LIST) {
				query.setPartyId(PartyUtility.getCurrentPartyId(request));
			}
			
			query.setSealId(getListRequest.getSealId());
			query.setDevicesStatus(getListRequest.getDevicesStatus());
			query.setOrderColumn(getListRequest.getOrder());
			query.setOrderType(getListRequest.getOrderby());
			query.setOffset((getListRequest.getPageNo() - 1)*getListRequest.getPageSize());
			query.setPageSize(getListRequest.getPageSize());
			query.setCompanyId(PartyUtility.getCurrentPartyCompanyId(request));
			query.setKeyword(getListRequest.getKeyword());
			
			PageModel<Devices> pm = devicesServices.getPageByQuery(query);
			if(pm != null) {
				response = GetListResponse.valueOf(pm, getTakeMap(pm));
			}
			response.setResult(ResultType.SUCCESS.getValue());
		}catch(Exception e) {
			logger.error("", e);
			response.setResult(ResultType.ERROR.getValue());
		}
		return response;
	}

	private Map<Long, DevicesTake> getTakeMap(PageModel<Devices> pm){
		Map<Long, DevicesTake> result = new HashMap<Long, DevicesTake>();
		
		if(pm == null ||  pm.getDatas() == null || pm.getDatas().isEmpty()) {
			return result;
		}
		
		List<Long> devicesIdList = new ArrayList<Long>();
		for(Devices devices : pm.getDatas()) {
			if(devices == null) {
				continue;
			}
			devicesIdList.add(devices.getDevicesId());
		}
		
		if(devicesIdList.isEmpty()) {
			return result;
		}
		
		DevicesTakeQuery devicesTakeQuery = new DevicesTakeQuery();
		devicesTakeQuery.setDevicesIds(StringUtils.join(devicesIdList, ","));
		devicesTakeQuery.setTakeStatus(TakeStatusEnum.WAIT_RETURN.getCode());
		List<DevicesTake> takeList = devicesTakeService.getListByQuery(devicesTakeQuery);
		if(takeList == null || takeList.isEmpty()) {
			return result;
		}
		
		for(DevicesTake devicesTake : takeList) {
			if(devicesTake == null) {
				continue;
			}
			result.put(devicesTake.getDevicesId(), devicesTake);
		}
		return result;
	}
	
	@RequestMapping("/devices/add")
	@ResponseBody
	public BaseResponse add(AddDevicesRequest request, HttpServletRequest httpRequest) {
		BaseResponse result = new BaseResponse();
		try {
			if(request == null) {
				throw new NeedBackMsgException("request is null");
			}
			
			if(request.getSealId() == null) {
				throw new NeedBackMsgException("sealId is null");
			}
			
			if(StringUtils.isBlank(request.getAlias())) {
				throw new NeedBackMsgException("alias is null");
			}
			
			if(StringUtils.isBlank(request.getDevicesCode())) {
				throw new NeedBackMsgException("devicesCode is null");
			}
			
			if(StringUtils.isBlank(request.getModel())) {
				throw new NeedBackMsgException("model is null");
			}
			
			if(StringUtils.isBlank(request.getProduceDate())) {
				throw new NeedBackMsgException("produceDate is null");
			}
			
			if(StringUtils.isBlank(request.getExpireDate())) {
				throw new NeedBackMsgException("expireDate is null");
			}
			
			if(StringUtils.isBlank(request.getDevicesVersion())) {
				throw new NeedBackMsgException("devicesVersion is null");
			}
			
			SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
			Devices devices = new Devices();
			devices.setSealId(request.getSealId());
			devices.setDevicesCode(request.getDevicesCode());
			devices.setModel(request.getModel());
			devices.setProduceDate(sdf.parse(request.getProduceDate()));
			devices.setExpireDate(sdf.parse(request.getExpireDate()));
			devices.setAlias(request.getAlias());
			devices.setDevicesVerson(request.getDevicesVersion());
			devices.setCompanyId(PartyUtility.getCurrentPartyCompanyId(httpRequest));
			devicesServices.save(devices);
			
			result.setResult(ResultType.SUCCESS.getValue());
		}catch(NeedBackMsgException ne) {
			logger.error("", ne);
			result.setResult(ResultType.ERROR.getValue());
			result.setErrorMsg(ne.getMessage());
		}catch(Exception e) {
			logger.error("", e);
			result.setResult(ResultType.ERROR.getValue());
		}
		return result;
	}
	
	@RequestMapping("/devices/detail")
	@ResponseBody
	public GetDetailResponse detail(GetDetailRequest request, HttpServletRequest httpRequest) {
		GetDetailResponse result = new GetDetailResponse();
		try {
			if(request == null) {
				throw new IllegalArgumentException("request");
			}
			if(request.getDevicesId() == null) {
				throw new IllegalArgumentException("request.getDevicesId");
			}
			Devices devices = devicesServices.getInfoById(request.getDevicesId());
			
			DevicesActQuery devicesActQuery = new DevicesActQuery();
			devicesActQuery.setPartyId(PartyUtility.getCurrentPartyId(httpRequest));
			devicesActQuery.setDevicesId(request.getDevicesId());
//			devicesActQuery.setWaitUse(true);
			devicesActQuery.setApplyType(ApplyTypeEnum.TEST_APPLY.getCode());
			List<DevicesAct> actList = devicesActService.getListByQuery(devicesActQuery);
			result.setData(devices, actList);
			result.setResult(ResultType.SUCCESS.getValue());
		}catch(Exception e) {
			logger.error("", e);
			result.setResult(ResultType.ERROR.getValue());
		}
		return result;
	}
	
	@RequestMapping("/devices/bind")
	@ResponseBody
	public BaseResponse bind(BindDevicesRequest request, HttpServletRequest httpRequest) {
		BaseResponse result = new BaseResponse();
		try {
			
			if(request == null) {
				throw new IllegalArgumentException("request");
			}
			
			if(StringUtils.isBlank(request.getSealName())) {
				throw new ParameterException("请输入印章名称");
			}
			
			if(request.getCustosPartyId() == null) {
				throw new ParameterException("请选择印章保管员");
			}
			
			if(request.getLimitUrgentApply() == null || request.getLimitUrgentApply() < 1) {
				throw new ParameterException("请输入紧急最大申请次数");
			}
			
			if(StringUtils.isBlank(request.getPartyIds())) {
				throw new ParameterException("请选择审核人员");
			}
			
			Seal seal = new Seal();
			seal.setCompanyId(PartyUtility.getCurrentPartyCompanyId(httpRequest));
			seal.setPartyId(request.getCustosPartyId());
			seal.setSealName(request.getSealName());
			seal.setIsForcedPhoto(request.getIsForcedPhoto());
			seal.setLimitUrgentApply(request.getLimitUrgentApply());
			seal.setDevicesId(request.getDevicesId());
			seal.setVerifyPartyIds(request.getPartyIds());
			seal.setSpecialPartyId(request.getSpecialPartyId());
			seal.setWorkflowType(WorkflowTypeEnum.QUEUE.code());
			seal.setUseSpecial("Y");
			
			devicesServices.setting(seal);
			result.setResult(ResultType.SUCCESS.getValue());
		}catch(ParameterException pe) {
			logger.error("", pe);
			result.setErrorMsg(pe.getMessage());
			result.setResult(ResultType.ERROR.getValue());
		}catch(Exception e ) {
			logger.error("", e);
			result.setResult(ResultType.ERROR.getValue());
		}
		return result;
	}
	
	@RequestMapping("/devices/startInstall")
	@ResponseBody
	public BaseResponse startInstall(InstallDevicesRequest request, HttpServletRequest httpRequest) {
		BaseResponse result = new BaseResponse();
		try {
			if(request == null) {
				throw new IllegalArgumentException("request");
			}
			
			if(request.getDevicesId() == null) {
				throw new IllegalArgumentException("request");
			}
			
			Long companyId = PartyUtility.getCurrentPartyCompanyId(httpRequest);
			if(companyId == null) {
				throw new RuntimeException("companyId is null");
			}
			
			String userLoginId = PartyUtility.getCurrentUserLoginId(httpRequest);
			devicesServices.install(request.getDevicesId(), companyId, userLoginId);
			result.setResult(ResultType.SUCCESS.getValue());
		}catch(Exception e) {
			logger.error("", e);
			result.setResult(ResultType.ERROR.getValue());
		}
		return result;
	}
	
	@RequestMapping("/devices/installConfirm")
	@ResponseBody
	public BaseResponse installConfirm(InstallDevicesRequest request, HttpServletRequest httpRequest) {
		BaseResponse result = new BaseResponse();
		try {
			if(request == null) {
				throw new IllegalArgumentException("request");
			}
			
			if(request.getDevicesId() == null) {
				throw new IllegalArgumentException("request");
			}
			
			Devices devices = new Devices();
			devices.setDevicesId(request.getDevicesId());
			devices.setCompanyId(PartyUtility.getCurrentPartyCompanyId(httpRequest));
			String userLoginId = PartyUtility.getCurrentUserLoginId(httpRequest);
			
			devicesServices.installConfirm(devices, userLoginId);
			result.setResult(ResultType.SUCCESS.getValue());
		}catch(Exception e) {
			logger.error("", e);
			result.setResult(ResultType.ERROR.getValue());
		}
		return result;
	}
	
	@RequestMapping("/devices/resetStatus")
	@ResponseBody
	public BaseResponse resetStatus(ResetStatusRequest request, HttpServletRequest httpRequest) {
		BaseResponse result = new BaseResponse();
		try {
			
			if(request == null) {
				throw new ParameterException("request");
			}
			
			if(request.getDevicesId() == null) {
				throw new ParameterException("request.devicesId");
			}
			
			devicesServices.resetStatus(request.getDevicesId(), PartyUtility.getCurrentUserLoginId(httpRequest));
			result.setResult(ResultType.SUCCESS.getValue());
		}catch(Exception e) {
			logger.error("", e);
			result.setResult(ResultType.ERROR.getValue());
		}
		return result;
	}
	
	@RequestMapping("/devices/setWorkflow")
	@ResponseBody
	public BaseResponse setWorkflow(SetWorkflowRequest request, HttpServletRequest httpRequest) {
		BaseResponse result = new BaseResponse();
		
		try {
			if(request == null) {
				throw new IllegalArgumentException("request");
			}
			
			Long companyId = PartyUtility.getCurrentPartyCompanyId(httpRequest);
			if(companyId == null) {
				throw new IllegalArgumentException("companyId");
			}
			String userLoginId = PartyUtility.getCurrentUserLoginId(httpRequest);
			
			devicesServices.setWorkflow(request.getDevicesId(), request.getWorkflowId(), companyId, userLoginId);
			result.setResult(ResultType.SUCCESS.getValue());
		}catch(Exception e) {
			logger.error("", e);
			result.setResult(ResultType.ERROR.getValue());
		}
		return result;
	}

	@RequestMapping("/devices/open")
	@ResponseBody
	public BaseResponse open(OpenRequest request, HttpServletRequest httpRequest) {
		
		BaseResponse result = new BaseResponse();
		try {
			
			if(request == null) {
				throw new IllegalArgumentException("request");
			}
			
			Long companyId = PartyUtility.getCurrentPartyCompanyId(httpRequest);
			if(companyId == null) {
				throw new IllegalArgumentException("companyId");
			}
			String userLoginId = PartyUtility.getCurrentUserLoginId(httpRequest);
			
			Devices devices = new Devices();
			devices.setDevicesId(request.getDevicesId());
			devices.setCompanyId(companyId);
			devicesServices.publish(devices, userLoginId);
			result.setResult(ResultType.SUCCESS.getValue());
		}catch(Exception e) {
			logger.error("", e);
			result.setResult(ResultType.ERROR.getValue());
		}
		return result;
	}
	
	
	@RequestMapping("/devices/setCust")
	@ResponseBody
	public BaseResponse setCust(SetCustRequest request, HttpServletRequest httpRequest) {
		BaseResponse result = new BaseResponse();
		try {
			
			if(request == null) {
				throw new IllegalArgumentException("request");
			}
			String userLoginId = PartyUtility.getCurrentUserLoginId(httpRequest);
			
			devicesServices.setCustos(request.getSealId(), request.getPartyId(), userLoginId);
			result.setResult(ResultType.SUCCESS.getValue());
		}catch(Exception e) {
			logger.error("", e);
			result.setResult(ResultType.ERROR.getValue());
		}
		return result;
	}
	
	@RequestMapping("/devices/setInterim")
	@ResponseBody
	public BaseResponse setInterim(SetInterimRequest request, HttpServletRequest httpRequest) {
		
		BaseResponse result = new BaseResponse();
		try {
			
			if(request == null) {
				throw new IllegalArgumentException("request");
			}
			
			if(request.getSealId() == null) {
				throw new IllegalArgumentException("request.sealId");
			}
			
			if(request.getPartyId() == null) {
				throw new IllegalArgumentException("request.partyId");
			}
			
			if(StringUtils.isBlank(request.getExpireTime())) {
				throw new IllegalArgumentException("request.partyId");
			}
			
			Seal seal = new Seal();
			seal.setSealId(request.getSealId());
			seal.setCompanyId(PartyUtility.getCurrentPartyCompanyId(httpRequest));
			seal.setInterimPartyId(request.getPartyId());
			
			seal.setInterimExpiredDate(new SimpleDateFormat("yyyy-MM-dd").parse(request.getExpireTime()));
			devicesServices.setInterim(seal);
			result.setResult(ResultType.SUCCESS.getValue());
		}catch(Exception e) {
			logger.error("", e);
			result.setResult(ResultType.ERROR.getValue());
		}
		return result;
	}
	
	@RequestMapping("/devices/edit")
	@ResponseBody
	public BaseResponse edit(EditSealRequest request, HttpServletRequest httpRequest) {
		BaseResponse result = new BaseResponse();
		try {
			
			if(request == null) {
				throw new IllegalArgumentException("request");
			}
			
			if(request.getSealId() == null) {
				throw new IllegalArgumentException("request.sealId");
			}
			
			if(StringUtils.isBlank(request.getName())) {
				throw new IllegalArgumentException("request.name");
			}
			
			Seal seal = new Seal();
			seal.setSealId(request.getSealId());
			seal.setSealName(request.getName());
			devicesServices.setName(seal);
			result.setResult(ResultType.SUCCESS.getValue());
		}catch(Exception e) {
			logger.error("", e);
			result.setResult(ResultType.ERROR.getValue());
		}
		return result;
	}	
	
	@RequestMapping("/devices/upgrade")
	@ResponseBody
	public BaseResponse upgrade(UpgradeRequest request) {
		
		BaseResponse result = new BaseResponse();
		try {
			
			if(request == null) {
				throw new IllegalArgumentException("request");
			}
			
			if(request.getDevicesId() == null) {
				throw new IllegalArgumentException("request.devicesId");
			}
			
			if(StringUtils.isBlank(request.getVersion())) {
				throw new IllegalArgumentException("request.version");
			}

			Devices devices = new Devices();
			devices.setDevicesId(request.getDevicesId());
			devices.setDevicesVerson(request.getVersion());
			devicesServices.upgrade(devices);
			result.setResult(ResultType.SUCCESS.getValue());
		}catch(Exception e) {
			logger.error("", e);
			result.setResult(ResultType.ERROR.getValue());
		}
		return result;
		
	}
	
	@RequestMapping("/devices/position")
	@ResponseBody
	public DevicesPositionResponse position(DevicesPositionRequest request, HttpServletRequest httpRequest) {
		
		DevicesPositionResponse result = new DevicesPositionResponse();
		try {
			
			if(request == null) {
				throw new IllegalArgumentException("request");
			}
			
			if(request.getSealId() == null) {
				throw new IllegalArgumentException("request.sealId");
			}
			
			
			SealQuery sealQuery = new SealQuery();
			sealQuery.setSealId(request.getSealId());
			sealQuery.setCompanyId(PartyUtility.getCurrentPartyCompanyId(httpRequest));
			Seal seal = sealServices.getInfoByQuery(sealQuery);
			if(seal == null) {
				throw new IllegalStateException("seal not exist");
			}
			
			DevicesQuery devicesQuery = new DevicesQuery();
			devicesQuery.setSealId(request.getSealId());
			Devices devices = devicesServices.getInfoByQuery(devicesQuery);
			
			if(devices == null) {
				throw new IllegalStateException("devices not exist");
			}
			DevicesTakeQuery takeQuery = new DevicesTakeQuery();
			takeQuery.setDevicesId(devices.getDevicesId());
			takeQuery.setTakeStatus(TakeStatusEnum.WAIT_RETURN.getCode());
			DevicesTake take = devicesTakeService.getInfoByQuery(takeQuery);

			result.setResultData(seal, take);
			result.setResult(ResultType.SUCCESS.getValue());
		}catch(Exception e) {
			logger.error("", e);
			result.setResult(ResultType.ERROR.getValue());
		}
		return result;
	}
	
	@RequestMapping("/devices/releaseInterim")
	@ResponseBody
	public BaseResponse releaseInterim(ReleaseInterimRequest request) {
		BaseResponse result = new BaseResponse();
		try {
			
			if(request == null) {
				throw new IllegalArgumentException("request");
			}
			
			if(request.getSealId() == null) {
				throw new IllegalArgumentException("request.sealId");
			}
			
			devicesServices.releaseInterim(request.getSealId());
			result.setResult(ResultType.SUCCESS.getValue());
		}catch(Exception e) {
			logger.error("", e);
			result.setResult(ResultType.ERROR.getValue());
		}
		return result;
	}
	
	@RequestMapping("/devices/syncStatus")
	@ResponseBody
	public BaseResponse syncStatus(SyncDevicesStatusRequest request) {
		
		BaseResponse result = new BaseResponse();
		try {
			
			if(request == null) {
				throw new IllegalArgumentException("request");
			}
			
			if(request.getDevicesId() == null) {
				throw new IllegalArgumentException("request.devicesId");
			}
			
			DevicesStatusEnum devicesStatus = DevicesStatusEnum.getByCode(request.getStatus());
			
			if(devicesStatus == null) {
				throw new IllegalArgumentException("devicesStatus");
			}
			
			Devices devices = new Devices();
			devices.setDevicesId(request.getDevicesId());
			devices.setDevicesStatus(devicesStatus.getCode());
			devicesServices.syncStatus(devices);
			result.setResult(ResultType.SUCCESS.getValue());
		}catch(Exception e) {
			logger.error("", e);
			result.setResult(ResultType.ERROR.getValue());
		}
		return result;
	}
	
	@RequestMapping("/devices/switchRunStatus")
	@ResponseBody
	public BaseResponse switchRunStatus(SwitchRunStatusRequest request, HttpServletRequest httpRequest) {
		BaseResponse result = new BaseResponse();
		try {
			
			if(request == null) {
				throw new IllegalArgumentException("request");
			}
			
			if(request.getDevicesId() == null) {
				throw new IllegalArgumentException("request.devicesId");
			}
			
			Devices devices = new Devices();
			devices.setDevicesId(request.getDevicesId());
			devices.setCompanyId(PartyUtility.getCurrentPartyCompanyId(httpRequest));
			result.setResult(ResultType.SUCCESS.getValue());
		}catch(Exception e) {
			logger.error("", e);
			result.setResult(ResultType.ERROR.getValue());
		}
		return result;
	}
}
